package main

import (
	"errors"
	"fmt"
	"strings"
)

const (
	DELIMITER string = " ;"
	SEPARATOR string = ","
	SPACES    string = " "
	NONESTR   string = ""
)
const ANNOTATION byte = ';'

type LogicLine struct {
	Line       int
	DeviceName string
	Action     string
	delimiter  string
	Err        error
	FullStr    string
	CaseExpr   *Expression
	LogicExpr  *Expression
}

func (ll *LogicLine) ConvertLine(str string, line int) {
	if ll.delimiter == "" {
		ll.delimiter = DELIMITER
	}
	if str[0] == ANNOTATION {
		return
	}
	ll.Line = line
	ll.FullStr = strings.ReplaceAll(str, " !", "")
	strSlice := strings.Split(ll.FullStr, ll.delimiter)
	if len(strSlice) != 4 {
		ll.Err = errors.New(fmt.Sprintf("[%d行]逻辑格式错误！存在多余或者缺少分割符[%s]", ll.Line, ll.delimiter))
		return
	}
	ll.DeviceName = strSlice[0]
	ll.Action = strings.ReplaceAll(strSlice[1], SPACES, NONESTR)
	ll.CaseExpr.str = strings.ReplaceAll(strSlice[2], SPACES, NONESTR)
	ll.CaseExpr.Unmarshal()
	ll.CaseExpr.line = ll.Line
	ll.LogicExpr.str = strings.ReplaceAll(strSlice[3], SPACES, NONESTR)
	ll.LogicExpr.Unmarshal()
	ll.LogicExpr.line = ll.Line
	ll.LogicExpr.FullStr = ll.FullStr
}

func NewLogicLine(filePath string) *LogicLine {
	ll := new(LogicLine)
	ll.LogicExpr = &Expression{filePath: filePath}
	ll.CaseExpr = &Expression{filePath: filePath}
	return ll
}

func BuildLogicalData(filePath string) LogicalDeviceMap {
	ch := make(chan string, 5)
	ReadFileToChan(filePath, ch)

	ldm := LogicalDeviceMap{}
	line := 0
	for c := range ch {
		if c == "" {
			continue
		}
		line++
		ll := NewLogicLine(filePath)
		ll.ConvertLine(c, line)
		if ll.FullStr == "" {
			continue
		}
		le := NewLogicalExpr(filePath, ll.FullStr, ll.DeviceName, ll.Action, line)
		if _lam, ok := ldm[ll.DeviceName]; !ok {
			err := le.setData(ll.CaseExpr, ll.LogicExpr, line)
			if err != nil {
				fmt.Println(err.Error())
				continue
			}
			ldm[ll.DeviceName] = LogicalActionMap{
				ll.Action: le,
			}
		} else {
			if _le, ok := _lam[ll.Action]; !ok {
				err := le.setData(ll.CaseExpr, ll.LogicExpr, line)
				if err != nil {
					fmt.Println(err.Error())
					continue
				}
				_lam[ll.Action] = le
			} else {
				err := _le.setData(ll.CaseExpr, ll.LogicExpr, line)
				if err != nil {
					fmt.Println(err.Error())
					continue
				}
			}

		}
	}
	//fmt.Printf("val is %v\n", ldm)
	return ldm
}

type Ignore struct {
	line           int
	device         string
	action         string
	caseExpr       *Expression
	fullStr        string
	ignoreCaseList []*Expression
}

func (ig *Ignore) ConvertLine(str string, line int) {
	strSlice := strings.Split(str, DELIMITER)
	if str[0] == ANNOTATION {
		return
	}
	if len(strSlice) >= 4 {
		caseExpr := new(Expression)
		ig.caseExpr = caseExpr
		ig.caseExpr.str = strings.ReplaceAll(strSlice[2], SPACES, NONESTR)
		ig.caseExpr.Unmarshal()
	}
	if len(strSlice) >= 3 {
		ig.action = strings.ReplaceAll(strSlice[1], SPACES, NONESTR)
	}
	if len(strSlice) >= 2 {
		ig.device = strSlice[0]
	} else {
		fmt.Printf("[%d行]格式错误！[%s]", line, str)
		return
	}
	ig.line = line
	ig.fullStr = ig.device + ig.action
}

func (ig *Ignore) CheckIgnore(device, action string, expr *LogicalExpr) bool {
	if ig.device != device {
		return false
	}
	if ig.action != action && ig.action != "" && action != "" {
		return false
	}
	if expr != nil && ig.caseExpr != nil {
		for i := range expr.CaseMultipleExpr {
			if CompareSlice(ig.caseExpr.expr, expr.CaseMultipleExpr[i].expr) {
				expr.CaseMultipleExpr = append(expr.CaseMultipleExpr[:i], expr.CaseMultipleExpr[i+1:]...)
			}
		}
	}
	fmt.Printf("忽略：%s，%s", ig.device, ig.action)
	return true
}

func GetIgnoreList(filePath string) []*Ignore {
	var igList []*Ignore
	ch := make(chan string, 2)
	ReadFileToChan(filePath, ch)
	line := 0
	for c := range ch {
		if c == "" {
			continue
		}
		line++
		ig := new(Ignore)
		ig.ConvertLine(c, line)
		igList = append(igList, ig)
	}
	return igList
}
